package com.share.device.service.impl;

import com.alibaba.nacos.client.naming.utils.CollectionUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.share.device.domain.Cabinet;
import com.share.device.domain.Station;
import com.share.device.domain.StationLocation;
import com.share.device.mapper.StationMapper;
import com.share.device.repository.StationLocationRepository;
import com.share.device.service.ICabinetService;
import com.share.device.service.IRegionService;
import com.share.device.service.IStationService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.bson.types.ObjectId;
import org.springframework.data.mongodb.core.geo.GeoJsonPoint;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class StationServiceImpl extends ServiceImpl<StationMapper, Station> implements IStationService {

    private final ICabinetService cabinetService;

    private final IRegionService regionService;

    private final StationLocationRepository stationLocationRepository;

    /**
     * 查询站点列表
     */
    @Override
    public List<Station> selectStationList(Station station) {
        List<Station> list = baseMapper.selectStationList(station);
        List<Long> cabinetIdList = list.stream().map(Station::getCabinetId).collect(Collectors.toList());
        Map<Long, String> cabinetIdToCabinetNoMap = new HashMap<>();
        if (!CollectionUtils.isEmpty(cabinetIdList)) {
            List<Cabinet> cabinetList = cabinetService.list(new LambdaQueryWrapper<Cabinet>().in(Cabinet::getId, cabinetIdList));
            cabinetIdToCabinetNoMap = cabinetList.stream().collect(Collectors.toMap(Cabinet::getId, Cabinet::getCabinetNo));
        }
        for (Station item : list) {
            item.setCabinetNo(cabinetIdToCabinetNoMap.get(item.getCabinetId()));
        }
        return list;
    }

    /**
     * 新增站点
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int saveStation(Station station) {
        String provinceName = regionService.getNameByCode(station.getProvinceCode());
        String cityName = regionService.getNameByCode(station.getCityCode());
        String districtName = regionService.getNameByCode(station.getDistrictCode());
        station.setFullAddress(provinceName + cityName + districtName + station.getAddress());
        this.save(station);

        // 同步站点位置信息到MongoDB
        StationLocation stationLocation = new StationLocation();
        stationLocation.setId(ObjectId.get().toString());
        stationLocation.setStationId(station.getId());
        stationLocation.setLocation(new GeoJsonPoint(station.getLongitude().doubleValue(), station.getLatitude().doubleValue()));
        stationLocation.setCreateTime(new Date());
        stationLocationRepository.save(stationLocation);
        return 1;
    }

    /**
     * 修改站点
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int updateStation(Station station) {
        String provinceName = regionService.getNameByCode(station.getProvinceCode());
        String cityName = regionService.getNameByCode(station.getCityCode());
        String districtName = regionService.getNameByCode(station.getDistrictCode());
        station.setFullAddress(provinceName + cityName + districtName + station.getAddress());
        this.updateById(station);

        // 同步站点位置信息到MongoDB
        StationLocation stationLocation = stationLocationRepository.getByStationId(station.getId());
        stationLocation.setLocation(new GeoJsonPoint(station.getLongitude().doubleValue(), station.getLatitude().doubleValue()));
        stationLocationRepository.save(stationLocation);
        return 1;
    }

    /**
     * 站点设置关联数据
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int setData(Station station) {
        this.updateById(station);

        // 更正柜机使用状态
        Cabinet cabinet = cabinetService.getById(station.getCabinetId());
        cabinet.setStatus("1");
        cabinetService.updateById(cabinet);
        return 1;
    }

    /**
     * 更新初始化数据
     */
    @Override
    public void updateData() {
        // 获取所有站点列表
        List<Station> stationList = this.list();
        log.info("获取到 {} 个站点数据", stationList.size());

        // 遍历每个站点，处理其位置信息
        for (Station station : stationList) {
            log.debug("处理站点 ID: {}", station.getId());

            // 检查数据库中是否已存在该站点的位置信息
            StationLocation stationLocation = stationLocationRepository.getByStationId(station.getId());

            if (stationLocation == null) {
                log.info("站点 ID {} 的位置信息不存在，创建新记录", station.getId());

                // 创建新的位置记录
                stationLocation = new StationLocation();
                stationLocation.setId(ObjectId.get().toString());
                stationLocation.setStationId(station.getId());

                // 设置地理位置坐标（经度, 纬度）
                stationLocation.setLocation(new GeoJsonPoint(station.getLongitude().doubleValue(), station.getLatitude().doubleValue()));

                stationLocation.setCreateTime(new Date());

                try {
                    // 保存新创建的位置记录到数据库
                    stationLocationRepository.save(stationLocation);
                    log.info("成功保存站点 ID {} 的位置信息", station.getId());
                } catch (Exception e) {
                    log.error("保存站点 ID {} 的位置信息失败: {}", station.getId(), e.getMessage(), e);
                }
            } else {
                log.debug("站点 ID {} 的位置信息已存在", station.getId());
            }
        }
    }

    /**
     * 获取站点
     */
    @Override
    public Station getByCabinetId(Long id) {
        return this.baseMapper.selectOne(new LambdaQueryWrapper<Station>().eq(Station::getCabinetId, id));
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean removeByIds(Collection<?> list) {
        for (Object id : list) {
            stationLocationRepository.deleteByStationId(Long.parseLong(id.toString()));
        }
        return super.removeByIds(list);
    }
}
